package com.fyy.minio.utils;

import com.fyy.minio.model.ObjItem;
import io.minio.*;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class MinioUtils {

    @Autowired
    private MinioClient minioClient;

    @Value("${minio.bucketName}")
    private String bucketName;

    /**
     * 判断bucket是否存在，不存在则创建
     * @param name 数据桶名称
     */
    public boolean existBucket(String name){
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder()
                    .bucket(name)
                    .build());
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 创建bucket
     * @param name 数据桶名称
     */
    public Boolean makeBucket(String name){
        try {
            boolean exists = existBucket(name);
            if(!exists){
                minioClient.makeBucket(MakeBucketArgs.builder()
                        .bucket(name)
                        .build());
            }
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除bucket
     * @param name 数据桶名称
     */
    public Boolean removeBucket(String name){
        try {
            boolean exists = existBucket(name);
            if(exists){
                minioClient.removeBucket(RemoveBucketArgs.builder()
                        .bucket(name)
                        .build());
            }
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 文件上传
     * @param multipartFiles 文件
     * @return 文件名
     */
    public List<String> uploadFiles(MultipartFile[] multipartFiles){
        List<String> names = new ArrayList<>(multipartFiles.length);
        for (MultipartFile file : multipartFiles) {
            String fileName = file.getOriginalFilename();
            String[] split = fileName.split("\\.");
            //重定义文件名
            if(split.length > 1){
                fileName = split[0] + "_"
                        + System.currentTimeMillis()
                        + "." + split[1];
            }else{
                fileName = fileName + System.currentTimeMillis();
            }
            InputStream in = null;
            try {
                in = file.getInputStream();
                minioClient.putObject(PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .stream(in,in.available(),-1)
                        .contentType(file.getContentType())
                        .build());
            } catch (Exception e){
                e.printStackTrace();
            }finally {
                if(in != null){
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            names.add(fileName);
        }
        return names;
    }

    /**
     * 下载文件
     * @param fileName 文件名
     */
    public ResponseEntity<byte[]> downloadFile(String fileName){
        ResponseEntity<byte[]> responseEntity = null;
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            in = minioClient.getObject(GetObjectArgs.builder()
                    .bucket(bucketName).build());
            out = new ByteArrayOutputStream();
            IOUtils.copy(in,out);
            byte[] bytes = out.toByteArray();
            HttpHeaders headers = new HttpHeaders();
            try {
                headers.add("Content-Disposition","attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
                headers.setContentLength(bytes.length);
                headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
                headers.setAccessControlAllowHeaders(Arrays.asList("*"));
            } catch (Exception e){
                e.printStackTrace();
            }
            responseEntity = new ResponseEntity<byte[]>(bytes,headers, HttpStatus.OK);
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            try {
                if(in != null)in.close();
                if(out != null)out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseEntity;
    }

    /**
     * 查看容器中的对象
     * @param bucketName 数据桶
     */
    public List<ObjItem> listObjects(String bucketName){
        Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
                .bucket(bucketName).build());
        List<ObjItem> objItems = new ArrayList<>();
        try {
            for (Result<Item> result : results) {
                Item item = result.get();
                ObjItem objItem = new ObjItem();
                objItem.setObjectName(item.objectName());
                objItem.setSize(item.size());
                objItems.add(objItem);
            }
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }
        return objItems;
    }

    /**
     * 批量删除文件对象
     * @param bucketName 数据桶
     * @param fileNames 文件集合
     */
    public Iterable<Result<DeleteError>> removeObjects(String bucketName,List<String> fileNames){
        List<DeleteObject> dos = fileNames.stream().map(file -> new DeleteObject(file)).collect(Collectors.toList());
        Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder()
                .bucket(bucketName).objects(dos).build());
        return results;
    }


}
